var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookie = require('cookie');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var app = express();


var server = require('http').createServer(app);
var io = require('socket.io').listen(server); 


var sqlite3 = require('sqlite3').verbose();
var crypto = require('crypto');
var db = null;
var dbPath = 'C:/server/tshock/tshock.sqlite';
var warps = [];
var users = [];


app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));

initialize();


app.get('/', function (req, res) {
    ensureCookieExists(req, res);
    var user = users[req.cookies.uid];
    var info = { url:'/' };
    if (user) {
        info.admin = user.Usergroup == 'superadmin';
        info.username = user.Username;
    }
    res.render('index', info);
});


app.get('/map', function (req, res) {
    ensureCookieExists(req, res);
    var user = users[req.cookies.uid];
    var info = { url: '/map' };
    if (user) {
        info.admin = user.Usergroup == 'superadmin';
        info.username = user.Username;
    }
    res.render('map', info);
});

app.get('/map/fullscreen', function (req, res) {
    res.render('mapfs', { warps: JSON.stringify(warps) });
});


app.get('/login', function (req, res) {
    ensureCookieExists(req, res);
     
    res.render('login');
});


app.get('/admin', function (req, res) {   
    var user = users[req.cookies.uid];
    
    if (!user) {
        res.redirect('/login');
    } else if (user.Usergroup != "superadmin") {
        res.redirect('/');
    } else {
        var user = users[req.cookies.uid];
        var info = { url: '/admin' };
        if (user) {
            info.admin = user.Usergroup == 'superadmin';
            info.username = user.Username;
        }
        res.render('admin', info);
    }
});


app.use(function (req, res, next) {
    res.render('error');
});


io.sockets.on('connection', function (socket) {
    var uid = cookie.parse(socket.handshake.headers['cookie']).uid;
    var user = users[uid];
    socket.on('login', function (data, callback) {
        checkUser(data, socket, uid, callback);
    });
});

function initialize() {
    db = new sqlite3.Database(dbPath);   
    loadWarps();
}


setInterval(function () {
    loadWarps();
}, 1000 * 60 * 30);


function loadWarps() {
    db.all("SELECT * FROM Warps", function (err, rows) {
        if (err) {
            console.log(err);
            return;
        }
        warps = [];
        for (var i = 0; i < rows.length; i++) {
            var row = rows[i];
            
            if (!row.Private || row.Private == 0) {
                warps[i] = { name: row.WarpName, x: row.X, y: row.Y };
            }
        }
    });
}

function checkUser(data, socket, uid, callback) {
    db.all("SELECT * FROM Users WHERE Username = @0", data.name, function (err, rows) {
        if (err) {
            console.log(err);
            callback(false, 'Unable to connect to user database!');
        } else if (rows.length == 1) {
            if (rows[0].Password == getSha512Hash(data.pass)) {
                users[uid] = rows[0];
                callback(true);
            } else {
                callback(false, 'Invalid password');
            }
        }
        else {
            callback(false, 'Username does not exist!\nPlease login to the server first and create an account.');
        }
    });
}

function getSha512Hash(pass) {
    return crypto.createHash('sha512').update(pass).digest('hex').toUpperCase();
}

function randomIntInc(low, high) {
    return Math.floor(Math.random() * (high - low + 1) + low);
}

function ensureCookieExists(req, res) {
    var uid;
    if (!req.cookies.uid) {
        uid = randomIntInc(1111111, 99999999);
        res.cookie('uid', uid, { maxAge: 900000, httpOnly: true });
    }
}

server.listen(3001);
module.exports = app.listen(3000);
